package src

import (
	"fmt"
	"next-ppt/method"
	"next-ppt/sql"
	"path/filepath"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// UserRegister 处理用户注册逻辑。
func UserRegister(c *gin.Context) {
	// 定义用户登录信息结构体
	type userLogin struct { // 用户登录信息结构体
		Name  string `json:"name"`  // 用户名
		Pwd   string `json:"pwd"`   // 密码
		Phone string `json:"phone"` // 手机号
		Email string `json:"email"` // 邮箱
		Info  string `json:"info"`  // 信息
		Type  string `json:"type"`  // 类型
		Token string `json:"token"` // Token
	}
	var data userLogin
	// 解析请求中的JSON数据
	err := method.ParseJSON(c, &data)
	if err != nil {
		return
	}
	// 若Token为空，则进行用户注册流程
	if data.Token == "" {
		// 检查必填参数是否为空
		if data.Name == "" || data.Pwd == "" || data.Phone == "" || data.Email == "" || data.Info == "" {
			c.JSON(200, gin.H{
				"message": "参数不能为空",
			})
			return
		}
		// 检查用户名是否已存在
		var username sql.User
		err := method.Db.Where("name = ?", data.Name).First(&username).Error
		if err == nil {
			c.JSON(200, gin.H{
				"message": "用户名已存在",
			})
			return
		}
		// 对密码进行加密
		hashpwd, err := method.HashPwd(data.Pwd)
		if err != nil {
			c.JSON(200, gin.H{
				"message": "密码加密失败",
			})
			return
		}

		// 创建新用户数据并保存到数据库
		dbdata := sql.User{
			Name:     data.Name,
			Password: hashpwd,
			Type:     data.Type,
			Phone:    data.Phone,
			Icon:     "/img/0.png",
			Time:     time.Now().Unix(),
			Info:     data.Info,
			Email:    data.Email,
		}
		err = method.Db.Create(&dbdata).Error
		if err != nil {
			c.JSON(200, gin.H{
				"message": "保存数据失败",
			})
			return
		}
		// 生成Token并保存
		token, err := method.CreateToken(int64(dbdata.ID))
		if err != nil {
			c.JSON(200, gin.H{
				"message": "token生成失败",
			})
		}

		tokenData := sql.Token{
			Token:      token,
			CreateTime: time.Now().Unix(),
			ExpireTime: time.Now().Unix() + 86400*method.Config.Server.ExpireTime,
			UserId:     int64(dbdata.ID),
		}
		err = method.Db.Create(&tokenData).Error
		if err != nil {
			c.JSON(200, gin.H{
				"message": "保存token失败",
			})
			return
		}
		// 返回注册成功信息及用户数据
		idstr := fmt.Sprintf("%d", dbdata.ID)
		c.JSON(200, gin.H{
			"message": "success",
			"main": struct {
				Name  string `json:"name"`  // 用户名
				Token string `json:"token"` // Token
				Icon  string `json:"icon"`  // 头像
				Info  string `json:"info"`  // 信息
				Type  string `json:"type"`  // 类型
				Email string `json:"email"` // 邮箱
				Phone string `json:"phone"` // 手机号
				Time  int64  `json:"time"`  // 注册时间
				ID    int64  `json:"id"`    // 用户ID
				Pwd   string `json:"pwd"`   // 加密后的密码
			}{
				Name:  dbdata.Name,
				Token: token,
				Icon:  method.Config.Server.ServerName + "api/userImg/" + idstr,
				Info:  dbdata.Info,
				Type:  dbdata.Type,
				Email: dbdata.Email,
				Phone: dbdata.Phone,
				Time:  dbdata.Time,
				ID:    int64(dbdata.ID),
				Pwd:   hashpwd,
			},
		})
	} else {
		// 若Token不为空，则提示已登录
		c.JSON(200, gin.H{
			"message": "当前已登录,请退出登录后再试",
		})
	}

}

// UserLogin 处理用户登录逻辑。
func UserLogin(c *gin.Context) {
	// 定义用户登录信息结构体
	type userLogin struct {
		Name  string `json:"name"`  // 用户名
		Pwd   string `json:"pwd"`   // 密码
		Token string `json:"token"` // Token
		Phone string `json:"phone"` // 手机号
		Email string `json:"email"` // 邮箱
		Type  string `json:"type"`  // 类型
	}
	var data userLogin
	// 解析请求中的JSON数据
	err := method.ParseJSON(c, &data)
	if err != nil {
		return
	}

	// 若Token为空，则进行用户登录流程
	if data.Token == "" {
		// 检查必填参数是否为空
		if data.Name == "" || data.Pwd == "" || data.Email == "" || data.Phone == "" {
			c.JSON(200, gin.H{
				"message": "参数不能为空",
			})
			return
		}
		// 处理管理员登录
		if data.Type == "admin" {
			var admin sql.User
			err := method.Db.Where("name = ? AND type = ?", data.Name, "admin").First(&admin).Error
			if err != nil {
				c.JSON(200, gin.H{
					"message": "管理员不存在",
				})
				return
			}
			// 验证密码、邮箱或手机号是否匹配
			if method.ComparePwd(admin.Password, data.Pwd) == true || data.Email == admin.Email || data.Phone == admin.Phone {
				newToken, err := method.CreateToken(int64(admin.ID))
				if err != nil {
					c.JSON(200, gin.H{
						"message": "token生成失败",
					})
					return
				}
				tokenData := sql.Token{
					Token:      newToken,
					CreateTime: time.Now().Unix(),
					ExpireTime: time.Now().Unix() + 86400*method.Config.Server.ExpireTime,
					UserId:     int64(admin.ID),
				}
				err = method.Db.Create(&tokenData).Error
				if err != nil {
					c.JSON(200, gin.H{
						"message": "保存token失败",
					})
					return
				}
				c.JSON(200, gin.H{
					"message": "success",
					"main": struct {
						Name  string `json:"name"`  // 用户名
						Token string `json:"token"` // Token
						Icon  string `json:"icon"`  // 头像
						Info  string `json:"info"`  // 信息
						Type  string `json:"type"`  // 类型
						Email string `json:"email"` // 邮箱
						Phone string `json:"phone"` // 手机号
						Time  int64  `json:"time"`  // 注册时间
						ID    int64  `json:"id"`    // 用户ID
					}{
						Name:  admin.Name,
						Token: newToken,
						Icon:  method.Config.Server.ServerName + "api/userImg/" + fmt.Sprintf("%d", admin.ID),
						Info:  admin.Info,
						Type:  admin.Type,
						Email: admin.Email,
						Phone: admin.Phone,
						Time:  admin.Time,
						ID:    int64(admin.ID),
					},
				})
				return
			}
			return
		}
		// 处理普通用户登录
		var username sql.User
		err := method.Db.Where("name = ?", data.Name).First(&username).Error
		if err != nil {
			c.JSON(200, gin.H{
				"message": "用户名不存在",
			})
			return
		}
		// 验证密码、邮箱或手机号是否匹配
		if method.ComparePwd(username.Password, data.Pwd) == true || username.Phone == data.Phone || username.Email == data.Email {
			newToken, err := method.CreateToken(int64(username.ID))
			if err != nil {
				c.JSON(200, gin.H{
					"message": "token生成失败",
				})
				return
			}
			tokenData := sql.Token{
				Token:      newToken,
				CreateTime: time.Now().Unix(),
				ExpireTime: time.Now().Unix() + 86400*method.Config.Server.ExpireTime,
				UserId:     int64(username.ID),
			}
			err = method.Db.Create(&tokenData).Error
			if err != nil {
				c.JSON(200, gin.H{
					"message": "保存token失败",
				})
				return
			}
			c.JSON(200, gin.H{
				"message": "success",
				"main": struct {
					Name  string `json:"name"`  // 用户名
					Token string `json:"token"` // Token
					Icon  string `json:"icon"`  // 头像
					Info  string `json:"info"`  // 信息
					Type  string `json:"type"`  // 类型
					Email string `json:"email"` // 邮箱
					Phone string `json:"phone"` // 手机号
					Id    int64  `json:"id"`
					Time  int64  `json:"time"` // 注册时间
				}{
					Name:  username.Name,
					Token: newToken,
					Icon:  method.Config.Server.ServerName + "api/userImg/" + fmt.Sprintf("%d", username.ID),
					Info:  username.Info,
					Type:  username.Type,
					Email: username.Email,
					Phone: username.Phone,
					Id:    int64(username.ID),
					Time:  username.Time,
				},
			})
			return
		} else {
			c.JSON(200, gin.H{
				"message": "信息错误",
			})
			return
		}
	} else {
		// 若Token不为空，则提示已登录
		c.JSON(200, gin.H{
			"message": "当前已登录,请退出登录后再试",
		})
		return
	}
}

func UserImg(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(200, gin.H{
			"message": "请输入用户ID",
		})
		return
	}
	if id == "0" {
		c.File("./img/0.png")
	}
	var user sql.User
	if err := method.Db.Where("id = ?", id).First(&user).Error; err != nil {
		c.JSON(200, gin.H{
			"message": "用户不存在",
		})
		return
	} else {

		c.File("." + user.Icon)
		return
	}
}

var imgUrl string

func ChangeImg(c *gin.Context) {
	token := c.PostForm("token")
	if token == "" {
		c.JSON(200, gin.H{
			"message": "请登录后再试",
		})
		return
	}
	userId, err := method.GetTokenId(token)
	if err != nil {
		c.JSON(200, gin.H{
			"message": "token错误",
		})
		return
	}
	// 获取上传的图片
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(200, gin.H{
			"message": "请上传图片",
		})
		return
	}
	if file.Size > 1024*1024*2 {
		c.JSON(200, gin.H{
			"message": "图片大小不能超过 2MB",
		})
		return
	}
	if file.Filename != "" {
		// 获取文件后缀
		ext := filepath.Ext(file.Filename)
		// 生成随机文件名
		randName := uuid.New().String()
		// 拼接文件名
		filename := randName + ext
		// 保存文件
		err = c.SaveUploadedFile(file, "./img/"+filename)
		if err != nil {
			c.JSON(200, gin.H{
				"message": "保存失败",
			})
			return
		}
		// 更新用户头像
		err = method.Db.Model(&sql.User{}).Where("id = ?", userId).Update("icon", "/img/"+filename).Error
		if err != nil {
			c.JSON(200, gin.H{
				"message": "更新失败",
			})
			return
		}

		imgUrl = method.Config.Server.ServerName + "api/userImg/" + fmt.Sprintf("%d", userId)

	}

	c.JSON(200, gin.H{
		"message": "success",
		"url":     imgUrl,
	})
}

func UserInfo(c *gin.Context) {
	type userInfo struct {
		Token string `json:"token"`
		Id    int64  `json:"id"`
	}
	var data userInfo
	if err := method.ParseJSON(c, &data); err != nil {
		c.JSON(200, gin.H{
			"message": "请输入正确的数据格式",
		})
		return
	}

	//fmt.Println(data)

	if data.Token == "" {
		c.JSON(200, gin.H{
			"message": "请登录后再试",
		})
		return
	}

	userId, err := method.GetTokenId(data.Token)
	if err != nil {
		c.JSON(200, gin.H{
			"message": "token错误",
		})
		return
	}

	if data.Id == int64(-1) { // 获取当前用户信息
		var userData sql.User
		err = method.Db.Where("id = ?", userId).First(&userData).Error
		if err != nil {
			c.JSON(200, gin.H{
				"message": "用户不存在",
			})
			return
		}
		var dataS = struct {
			Name  string `json:"name"`
			Phone string `json:"phone"`
			Email string `json:"email"`
			Info  string `json:"info"`
			Icon  string `json:"icon"`
			Type  string `json:"type"`
			Time  int64  `json:"time"`
			Id    int64  `json:"id"`
		}{
			Name:  userData.Name,
			Phone: userData.Phone,
			Email: userData.Email,
			Info:  userData.Info,
			Icon:  method.Config.Server.ServerName + "api/userImg/" + fmt.Sprintf("%d", userId),
			Type:  userData.Type,
			Time:  userData.Time,
			Id:    int64(uint(userData.ID)),
		}

		c.JSON(200, gin.H{
			"message": "success",
			"data":    dataS,
		})
	} else { // 获取指定用户信息
		var userData sql.User
		if err := method.Db.Where("id = ?", data.Id).First(&userData).Error; err != nil {
			c.JSON(200, gin.H{
				"message": "用户不存在",
			})
			return
		} else {
			var dataS = struct {
				Name  string `json:"name"`
				Email string `json:"email"`
				Info  string `json:"info"`
				Icon  string `json:"icon"`
				Type  string `json:"type"`
				Time  int64  `json:"time"`
				Id    int64  `json:"id"`
			}{
				Name:  userData.Name,
				Email: userData.Email,
				Info:  userData.Info,
				Icon:  method.Config.Server.ServerName + "api/userImg/" + fmt.Sprintf("%d", userData.ID),
				Type:  userData.Type,
				Time:  userData.Time,
				Id:    int64(uint(userData.ID)),
			}

			c.JSON(200, gin.H{
				"message": "success",
				"data":    dataS,
			})
		}
	}

}
